package com.zm.util;

import ch.ethz.ssh2.*;
import com.jcraft.jsch.*;
import com.jcraft.jsch.Session;
import com.zm.core.config.GetParamsByProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by ZM on 2022/2/10 9:44
 */
public class UploadFileToServerUtil {
    private static String uploadPath= GetParamsByProperties.readProperties("remote.uploadPath");
    //上传文件到指定服务器的目录下
    //@Async//待上传的文件、路径、新的远程文件名名称
    public static void uploadFile(Connection connection, File file, String remoteFileName) throws IOException {

        if (connection==null){
            throw new RuntimeException("连接不存在！");
        }else if (file == null || !file.exists()) {
            throw new RuntimeException("请确保上传文件不为空且存在！");
        }else if(remoteFileName==null || "".equals(remoteFileName.trim())){
            throw new RuntimeException("远程服务器新建文件名不能为空!");
        }
        //有抛异常就是失败，没有就是成功
        remoteUploadFile(connection, file, remoteFileName);

    }

    private static void remoteUploadFile( Connection connection,File file,
                                          String remoteFileName) throws IOException {
        ch.ethz.ssh2.Session session = null;
        SCPOutputStream scpo = null;
        FileInputStream fis = null;
        SFTPv3Client sftPv3Client=null;
//若文件路径是确定存在的，则不需要再去判断不存在重新创建文件夹了
        try {
            sftPv3Client=new SFTPv3Client(connection);//获取一个sftPv3Client对象，用来判断与创建文件夹的
            session = connection.openSession();// 打开一个会话
            createDir(session,sftPv3Client);//查看路径是否存在，不存在则创建新的文件夹
            SCPClient scpClient = connection.createSCPClient();

            scpo = scpClient.put(remoteFileName, file.length(), uploadPath, "0666");
            fis = new FileInputStream(file);

            byte[] buf = new byte[1024];
            int hasMore = fis.read(buf);

            while(hasMore != -1){
                scpo.write(buf);
                hasMore = fis.read(buf);
            }
        } catch (IOException e) {
            throw new IOException("SSH上传文件至服务器出错"+e.getMessage());
        }finally {
            if(null != fis){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(null != scpo){
                try {
                    scpo.flush();
                    scpo.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(null != session){
                session.close();
            }
            //通过连接池传进来的connection，这里不用关闭，释放手动释放connection就ok
//            if(null != connection){
//                connection.close();
//            }
        }
    }

    //若文件路径是确定存在的，则不需要再去判断不存在重新创建文件夹了
    private static boolean createDir(ch.ethz.ssh2.Session session, SFTPv3Client client){

        if (isDirExist(uploadPath,client)) {//判断存放目录的绝对路径是否存在
            client.close();//如果存在则关闭SFTPv3Client
            return true;
        }else {
            String pathArry[] = uploadPath.split("/");
            StringBuffer filePath=new StringBuffer("/");
            for (String path : pathArry) {//一级一级循环，
                if (path.equals("")) {
                    continue;
                }
                filePath.append(path + "/");//从/后面的第一级目录开始
                try {

                    if (!isDirExist(filePath.toString(),client)) {//判断每一级的目录是否存在
                        //如果不存在则 建立层级目录
                        client.mkdir(filePath.toString(), 0774);//权限码：0600为rw，具体参考linux权限知识
                        //0ugo，第二位u是user、第三位g是组、第四位o是其他人。在这里使用的是组成员zm
                        // 0是(no excute , no write ,no read)1是 excute, (no write, no read)
                        // 2是write，3是write、 excute，4是read，5是 read、excute，6是read、write ，7是read、write、excute
                    }
                } catch ( Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException("SFTP无法正常操作服务器"+e.getMessage());
                }
            }
        }
        client.close();
        session.close();
        return true;
    }

    private static boolean isDirExist(String directory, SFTPv3Client client) {
        boolean isDirExistFlag = false;
        try {
            SFTPv3FileAttributes lstat =  client.lstat(directory);
            isDirExistFlag = true;
            return lstat.isDirectory();
        } catch (Exception e) {
            if (e.getMessage().toLowerCase().equals("no such file")) {
                isDirExistFlag = false;
            }
        }
        return isDirExistFlag;
    }
}
